package cn.ycq.im.controller;

import cn.ycq.im.commons.annotation.Router;
import cn.ycq.im.commons.exceptions.ServiceException;
import cn.ycq.im.commons.utils.Https;
import cn.ycq.im.commons.utils.JwtUtis;
import cn.ycq.im.commons.utils.QrCodeHelper;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.github.hui.quick.plugin.qrcode.helper.QrCodeGenerateHelper;
import com.github.hui.quick.plugin.qrcode.wrapper.QrCodeGenWrapper;
import com.google.zxing.WriterException;
import com.sun.org.apache.xpath.internal.operations.Bool;
import io.netty.buffer.Unpooled;
import io.netty.handler.codec.http.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Controller;
import org.springframework.util.ObjectUtils;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.time.Instant;
import java.time.temporal.ChronoUnit;
import java.time.temporal.TemporalUnit;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

/**
 * @author yuchaoqun
 * @email chaoqunyu9311@163.com
 * @date 2021.03.15 20:33
 */

@Controller
@Slf4j
public class CodeController {

    private final Map<String, QrCodeContext> qrcodContexts = new ConcurrentHashMap<>();

    @Router(method = "get", uri = "/qrCode")
    public void qrCode(FullHttpRequest httpRequest, FullHttpResponse response) throws Exception {
        String channelId = UUID.randomUUID().toString();
        Instant instant = Instant.now().plus(5, ChronoUnit.MINUTES);
        long milli = instant.toEpochMilli();

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("channelId", channelId);

        QrCodeContext qrCodeContext = new QrCodeContext();
        qrCodeContext.timeout = milli;
        qrCodeContext.code = 0;
        qrCodeContext.channelId = channelId;
        qrcodContexts.put(channelId, qrCodeContext);

        String image = QrCodeGenWrapper.of("login:=" + jsonObject.toJSONString())
                .setW(300)
                .asString();

        JSONObject res = new JSONObject();
        res.put("code", 200);
        res.put("data", image);
        res.put("channelId",channelId);
        Https.ResponseUtils.writeJSONByObject(response, res);
    }

    @Router(method = "post", uri = "/scanCode")
    public void scanCode(FullHttpRequest httpRequest, FullHttpResponse response) throws Exception {
        String requestBody = Https.RequestUtils.getRequestBodyToString(httpRequest);
        JSONObject body = JSON.parseObject(requestBody);
        String channelId = body.getString("channelId");

        QrCodeContext qrCodeContext = qrcodContexts.get(channelId);
        if (ObjectUtils.isEmpty(qrCodeContext)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", 500);
            jsonObject.put("msg", "二维码无效");
            Https.ResponseUtils.writeJSONByObject(response, jsonObject);
            return;
        }

        long timeout = qrCodeContext.timeout;
        long nowTime = Instant.now().toEpochMilli();
        if (timeout >= nowTime) {
            qrCodeContext.code = 2;
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", 200);
            jsonObject.put("msg", "已设置扫码状态");
            Https.ResponseUtils.writeJSONByObject(response, jsonObject);

        } else {
            qrCodeContext.code = 1;
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", 500);
            jsonObject.put("msg", "二维码无效");
            Https.ResponseUtils.writeJSONByObject(response, jsonObject);
        }
    }

    @Router(method = "post", uri = "/confim")
    public void confim(FullHttpRequest httpRequest, FullHttpResponse response) throws Exception {
        String requestBody = Https.RequestUtils.getRequestBodyToString(httpRequest);
        JSONObject body = JSON.parseObject(requestBody);
        String channelId = body.getString("channelId");
        Boolean accept = body.getBoolean("accept");

        QrCodeContext qrCodeContext = qrcodContexts.get(channelId);
        if (ObjectUtils.isEmpty(qrCodeContext)) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", 500);
            jsonObject.put("msg", "二维码无效");
            Https.ResponseUtils.writeJSONByObject(response, jsonObject);
            return;
        }
        if (qrCodeContext.code != 2) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", 500);
            jsonObject.put("msg", "二维码无效");
            Https.ResponseUtils.writeJSONByObject(response, jsonObject);
            qrcodContexts.remove(channelId);
            return;
        }

        if (!accept) {
            qrCodeContext.code = 3;
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", 200);
            jsonObject.put("data", "0");
            jsonObject.put("msg", "扫码取消确认");
            Https.ResponseUtils.writeJSONByObject(response, jsonObject);
            return;
        }else{
            qrCodeContext.code = 4;
            String token = httpRequest.headers().get("token");
            DecodedJWT decodedJWT = JwtUtis.parseJwt(token);
            Claim uidC = decodedJWT.getClaim("uid");

            HashMap<String, String> hashMap = new HashMap<>();
            hashMap.put("uid", uidC.asString());
            qrCodeContext.token = JwtUtis.createJwtStr(hashMap,7, TimeUnit.DAYS);
        }

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", 200);
        jsonObject.put("data", "1");
        jsonObject.put("msg", "扫码确认完成");
        Https.ResponseUtils.writeJSONByObject(response, jsonObject);
    }

    @Router(method = "post", uri = "/vaildScanCode")
    public void vaildScanCode(FullHttpRequest httpRequest, FullHttpResponse response) throws Exception {
        String requestBody = Https.RequestUtils.getRequestBodyToString(httpRequest);
        JSONObject body = JSON.parseObject(requestBody);
        String channelId = body.getString("channelId");

        QrCodeContext qrCodeContext = qrcodContexts.get(channelId);
        if (qrCodeContext == null) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", 200);
            jsonObject.put("status", 1);
            Https.ResponseUtils.writeJSONByObject(response, jsonObject);
            return;
        }

        if (qrCodeContext.code == 1) {
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("code", 200);
            jsonObject.put("status", 1);
            Https.ResponseUtils.writeJSONByObject(response, jsonObject);
            qrcodContexts.remove(channelId);
            return;
        }

        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", 200);
        jsonObject.put("status", qrCodeContext.code);
        jsonObject.put("token", qrCodeContext.token);
        Https.ResponseUtils.writeJSONByObject(response, jsonObject);
    }

    class QrCodeContext {
        private long timeout;
        public int code;
        public String token;
        public String channelId;
    }

}
